package com.cloudkinto.service.mail.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cloudkinto.common.common.DateUtils;
import com.cloudkinto.common.exception.BizException;
import com.cloudkinto.common.utils.EmojiConverterUtil;
import com.cloudkinto.common.utils.ExcelUtils;
import com.cloudkinto.common.utils.dict.StaticDict;
import com.cloudkinto.dao.*;
import com.cloudkinto.entity.*;
import com.cloudkinto.service.file.FileService;
import com.cloudkinto.service.mail.MailService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.cloudkinto.common.web.PageResult;
import com.cloudkinto.common.web.SingleResult;

import com.cloudkinto.service.orderoutput.OrderOutputService;
import com.cloudkinto.service.orderoutput.vo.OrderOutputTrackNumberExcelImport;
import com.cloudkinto.service.tailtrucks.TailTrucksService;
import com.sun.mail.imap.IMAPStore;
import org.apache.commons.collections.BinaryHeap;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.transaction.annotation.Transactional;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * service实现类
 * </p>
 *
 * @author hua
 * @since 2022-11-22
 */
@Service
@Transactional(rollbackFor = Exception.class)//事务回滚
public class MailServiceImpl extends ServiceImpl<MailDao, MailDo> implements MailService {
    @Autowired
    private MailDao dao;
    @Autowired
    private FileService fileService;
    @Autowired
    private FileMoreDao fileMoreDao;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private MailAccountDao mailAccountDao;
    @Autowired
    private TailTrucksDao tailTrucksDao;
    @Autowired
    private TailTrucksService tailTrucksService;
    @Autowired
    private TailTrucksAmazonTimeDao tailTrucksAmazonTimeDao;
    @Autowired
    private OrderOutputService orderOutputService;
    //临时存储路径
    @Value("${gbc.uploadPath.filePathTemp}")
    private String filePathTemp;


    private final String mailNewSyncList = "mailNewSyncList";
    private final String mailAllSyncList = "mailAllSyncList";

    @Override
    public SingleResult addInit() {
        return SingleResult.success("");
    }

    @Override
    public Object add(Object req, Long userId) {
        MailDo entityDo = new MailDo();
        BeanUtils.copyProperties(req, entityDo);
        handlerAddBefore(entityDo, userId);
        dao.insert(entityDo);
        return handlerAddAfter(entityDo);
    }

    //新增校验
    private void addCheck(Object req) {

    }

    //做新增之前要执行的业务定制处理
    private void handlerAddBefore(MailDo entityDo, Long userId) {

        entityDo.setDeleteFlag(0);
    }

    //将新增的do转换成要返回的实体
    private Object handlerAddAfter(MailDo entityDo) {
        Object res = new Object();
        BeanUtils.copyProperties(entityDo, res);
        return res;
    }

    @Override
    public SingleResult updateInit(Long id) {
        return SingleResult.success("");
    }

    @Override
    public Object update(Object req, Long userId) {
        /*MailDo entityDo = dao.selectById(req.getId());
        BeanUtils.copyProperties(req, entityDo);
        handlerUpdateBefore(entityDo, userId);
        dao.updateById(entityDo);
        return handlerUpdateAfter(entityDo);*/
        return null;
    }

    //编辑校验
    private void updateCheck(Object req) {

    }

    //做修改之前要执行的业务定制处理
    private void handlerUpdateBefore(MailDo entityDo, Long userId) {
        entityDo.setUpdateBy(userId);
        entityDo.setUpdateTime(new Date());
    }

    //做修改之后要执行的业务定制处理
    private Object handlerUpdateAfter(MailDo entityDo) {
        Object res = new Object();
        BeanUtils.copyProperties(entityDo, res);
        return res;
    }

    @Override
    public int delete(Long id, Long userId) {
        MailDo entityDo = dao.selectById(id);
        handlerDeleteBefore(entityDo, userId);
        return dao.deleteById(id);
    }

    //做删除之前要执行的业务定制处理
    private void handlerDeleteBefore(MailDo entityDo, Long userId) {
        entityDo.setDeleteBy(userId);
        entityDo.setDeleteTime(new Date());
    }

    @Override
    public Object detail(Long id) {
        MailDo entityDo = dao.selectById(id);
        Object res = new Object();
        BeanUtils.copyProperties(entityDo, res);
        return handlerDetailAfter(res);
    }

    //查询明细之后要执行的业务定制处理
    private Object handlerDetailAfter(Object res) {
        return res;
    }

    @Override
    public SingleResult pageInit() {
        return SingleResult.success("");
    }

    @Override
    public List<Object> getList(Map<String, String> map) {
        QueryWrapper<MailDo> wrapper = queryBuild(map);
        List<MailDo> list = this.list(wrapper);
        List<Object> result = handlerListAfter(list);
        return result;
    }

    @Override
    public PageResult getListPage(Map<String, String> map) {
        QueryWrapper<MailDo> wrapper = queryBuild(map);
        IPage<MailDo> page = pageInit(map);
        page = this.page(page, wrapper);
        List<Object> resList = handlerListAfter(page.getRecords());
        PageResult result = new PageResult(resList, (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());
        return result;
    }

    //查询分页列表之后对列表数据的处理
    private List<Object> handlerListAfter(List<MailDo> list) {
        List<Object> result = new ArrayList<>();
        return result;
    }

    private IPage<MailDo> pageInit(Map<String, String> map) {
        IPage<MailDo> page = new Page();
        page.setSize(StringUtils.isNotBlank(map.get("pageSize")) ? Long.parseLong(map.get("pageSize")) : 10);
        page.setCurrent(StringUtils.isNotBlank(map.get("current")) ? Long.parseLong(map.get("current")) : 1);
        return page;
    }

    private QueryWrapper<MailDo> queryBuild(Map<String, String> map) {
        QueryWrapper<MailDo> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(map.get("keyword"))) {
            wrapper.like("keyword", map.get("keyword"));
        }
        return wrapper;
    }

    @Override
    public void timingSynchronizationMail(String type) {//mail.manualSyncOne.oneAccount  10分钟同步一次  mail.autoSyncOne.oneAccount4
        long currency = System.currentTimeMillis();
//        dao.deleteMail();
        MailAccountDo mailAccountDo = mailAccountDao.selectById(1);
        if (mailAccountDo == null) {
            return;
        }
        Double time = redisTemplate.opsForZSet().score(mailNewSyncList, mailAccountDo.getId());
        Double allTypeTime = redisTemplate.opsForZSet().score(mailAllSyncList, mailAccountDo.getId());//all类型同步时间
        int count = 0;
        if ("all".equals(type) && count <= 5) {
            //如果有all类型在同步 return
            if (allTypeTime != null && (currency - allTypeTime) < 60 * 60 * 1000) {
                return;
            }
            boolean flag = true;
            for (int i = 0; i < 5; i++) {
                currency = System.currentTimeMillis();
                if (time != null && (currency - time) < 60 * 1000 * 10) { //8分钟内同步过再等等（存的时候会少存2分钟）
                    try {
                        count += 1;
                        Thread.sleep(1000 * 15);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                return;
            }
            //将all类型同步时间更新到现在
            redisTemplate.opsForZSet().add(mailAllSyncList, mailAccountDo.getId(), currency);//
            try {
                this.syncByAccountId(mailAccountDo.getSmtp(), mailAccountDo.getImap(), mailAccountDo.getMailNo(), mailAccountDo.getPassword(), mailAccountDo.getId(), type);
            } catch (Exception e) {
                e.printStackTrace();
            }
            //同步结束后将 同步时间更新到两天前
            redisTemplate.opsForZSet().add(mailAllSyncList, mailAccountDo.getId(), currency - 60 * 60 * 24 * 1000);

        } else if ("new".equals(type) && (time == null || (currency - time) >= 60 * 10 * 1000) && (allTypeTime == null || (currency - allTypeTime) >= 60 * 60 * 1000)) {//new类型 且 10分钟之内未同步，且all类型不在同步或同步时间1小时之后
            //1个小时(用来同步ALL) 必更新
            redisTemplate.opsForZSet().add(mailNewSyncList, mailAccountDo.getId(), currency - 120 * 1000);
            try {
                this.syncByAccountId(mailAccountDo.getSmtp(), mailAccountDo.getImap(), mailAccountDo.getMailNo(), mailAccountDo.getPassword(), mailAccountDo.getId(), type);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            try {
                this.syncByAccountId(mailAccountDo.getSmtp(), mailAccountDo.getImap(), mailAccountDo.getMailNo(), mailAccountDo.getPassword(), mailAccountDo.getId(), type);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }


    public void syncByAccountId(String smtpHost, String imapHost, String mailNo, String password, Long accountId, String type) {
        Store store = null;
        try {
            store = getIMAPStore(smtpHost, imapHost, mailNo, password);
            Folder[] fArr = store.getDefaultFolder().list();

            // 获得收件箱
            syncOneFolder(fArr, accountId, mailNo, smtpHost, type);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (store != null) {
                try {
                    store.close();
                } catch (MessagingException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    public void syncOneFolder(Folder[] fArr, Long accountId, String mailNo, String smptHost, String type) throws Exception {

        for (Folder folder : fArr) {
//            if (!StaticDict.Mail_Folder_Type.INBOX.getValue().equals(folder.getName())) { //只同步发件箱 测试时打开
//                continue;
//            }

            if (StaticDict.Mail_Folder_Type.Other.getValue().equals(folder.getFullName()) || StaticDict.Mail_Folder_Type.Other.getGmail().equals(folder.getFullName())
                    || StaticDict.Mail_Folder_Type.Other.getSina().equals(folder.getFullName())) {
                //其他文件他，即自定义文件夹
                syncOneFolder(folder.list(), accountId, mailNo, smptHost, type);
            }
            // 以读写模式打开收件箱
            if (StaticDict.Mail_Folder_Type.Other.getValue().equals(folder.getFullName()) || StaticDict.Mail_Folder_Type.Other.getGmail().equals(folder.getFullName())
                    || StaticDict.Mail_Folder_Type.Other.getSina().equals(folder.getFullName())) {
                continue;
            }

            if (!"FBA约仓".equals(folder.getName()) && !"发票邮件".equals(folder.getName()) && !"SKL".equals(folder.getName())) { //OMS只同步固定文件夹
                continue;
            }

            System.out.println(mailNo + "::::" + folder.getName());
            folder.open(Folder.READ_ONLY);
            // 得到收件箱文件夹信息，获取邮件列表
            String folderName = folder.getName();
            if (StaticDict.Mail_Type.NetEase.getSmtp().equals(smptHost)) {
                folderName = StaticDict.Mail_Folder_Type.getValueByEase(folderName);
            } else if (StaticDict.Mail_Type.Sina.getSmtp().equals(smptHost)) {
                folderName = StaticDict.Mail_Folder_Type.getValueBySina(folderName);
            } else if (StaticDict.Mail_Type.Outlook.getSmtp().equals(smptHost)) {
                folderName = StaticDict.Mail_Folder_Type.getValueByOutlook(folderName);
            } else if (StaticDict.Mail_Type.Gmail.getSmtp().equals(smptHost)) {
                //INBOX 已删除邮件 已加星标 重要 草稿 所有邮件 已发邮件
                folderName = StaticDict.Mail_Folder_Type.getValueByGmail(folderName);
            }
            if (org.apache.commons.lang3.StringUtils.isBlank(folderName)) {
                folderName = folder.getName();
            }
            if ("所有邮件".equals(folderName)) {
                continue;
            }
            //查看是否有新邮件
            int newCount = 0;
            Message[] msgArr = folder.getMessages();
            int total = folder.getMessageCount();//总邮件数
            if ("new".equals(type) && total > 0) {
                Collections.reverse(Arrays.asList(msgArr));
            }

            //最近一封邮件的时间
            MailDo mailDo = dao.selectOne(new LambdaQueryWrapper<MailDo>()
                    .eq(MailDo::getShopMailAccountId, accountId)
                    .eq(MailDo::getFolderName, folderName)
                    .ne(MailDo::getType, StaticDict.Mail_Folder_Type.DRAFTS.getValue()).eq(MailDo::getStatus, "success")
                    .isNotNull(MailDo::getReceivedDate)
                    .last("order by received_date desc limit 1"));
            Date syncDate = mailDo == null ? DateUtils.passingDate(new Date(), -30) : new Date(mailDo.getReceivedDate().getTime() - 1000 * 60);
//            Date date = DateUtils.stringFormatToDate("2022-02-23");
            List<Message> syncMessageList = new ArrayList<>();
            for (int i = newCount; i < total; i++) {
                Message a = msgArr[i];
                try {
                    //最新11分钟 就同步
                    if (("new".equals(type) && a.getReceivedDate().getTime() >= syncDate.getTime()) || "all".equals(type)) {
//                if (StaticDict.Mail_Folder_Type.OUTBOX.getValue().equals(folder.getName())) { //只同步发件箱
                        syncMessageList.add(a);
                        //}
                    } else {
                        break;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            // }
            //使得邮箱都是按照收件日期正序排序,方便后期sql查询
            if ("new".equals(type)) {
                Collections.reverse(syncMessageList);
            }
            for (Message message : syncMessageList) {
                syncOneMailMsg(message, folderName, accountId, mailNo);
            }
            Folder[] childFolder = folder.list();
            folder.close(false);
            if (childFolder.length > 0) {
                this.syncOneFolder(childFolder, accountId, mailNo, smptHost, type);
            }
        }
    }


    public void syncOneMailMsg(Message a, String type, Long accountId, String mailNo) throws Exception {
        String folderName = type;//type区别收件发件 folderName区分属于哪个自定义文件夹
        boolean isRead = false;
        try {
            isRead = isNew(a);
        } catch (Exception e) {
            e.printStackTrace();
        }
        MimeMessage mimeMessage = (MimeMessage) a;
        String msgId = mimeMessage.getMessageID();
        String[] ids = a.getHeader("Message-Id");
        if (ids != null) {
            msgId = StringUtils.join(ids, ",");
        }
        MailDo et = dao.selectOne(new LambdaQueryWrapper<MailDo>().eq(MailDo::getMsgId, msgId).eq(MailDo::getShopMailAccountId, accountId).orderByDesc(MailDo::getId).last(" limit 1"));
        if (et != null) {
            return;
        }
        String[] customIds = a.getHeader("custom_id");
        String customId = org.apache.commons.lang3.StringUtils.join(customIds);
        if (org.apache.commons.lang3.StringUtils.isNotBlank(customId)) {
            et = dao.selectOne(new LambdaQueryWrapper<MailDo>().eq(MailDo::getCustomId, customId).eq(MailDo::getShopMailAccountId, accountId));

        }
        StringBuilder plain = new StringBuilder();
        StringBuilder html = new StringBuilder();

        //获取邮箱正文
        getMailContent(a, plain, html);
        //收件人
//        String to = syncMailAddress(Message.RecipientType.TO, a);
        String cc = syncMailAddress(Message.RecipientType.CC, a);

        MailDo mailDo = new MailDo();
        mailDo.setCc(cc);
        mailDo.setIsRead(isRead);

        String parsedPlain = EmojiConverterUtil.emojiConvert1(plain.toString());
        String parsedHtml = EmojiConverterUtil.emojiConvert1(html.toString());

//        mailDo.setTextPlain(parsedPlain.length() <= 65000 ? parsedPlain : "内容过长");
//        mailDo.setTextHtml(parsedHtml.length() <= 65000 ? parsedHtml : "内容过长");

        mailDo.setTextPlain(parsedPlain);
        mailDo.setTextHtml(parsedHtml);

        mailDo.setContentType(a.getContentType());
//        mailDo.setMailTo(to);

        InternetAddress[] addresses = (InternetAddress[]) mimeMessage.getReplyTo();
        StringBuilder relyTo = new StringBuilder();
        for (InternetAddress add : addresses) {
            if (relyTo.length() > 0) {
                relyTo.append(";");
            }
            String email = add.getAddress();
            if (email == null)
                email = "";
            else {
                email = MimeUtility.decodeText(email);
            }
            String personal = add.getPersonal();
            if (personal == null)
                personal = "";
            else {
                personal = MimeUtility.decodeText(personal);
            }
            String compositeto = personal + "<" + email + ">";
            relyTo.append(MimeUtility.decodeText(compositeto));
        }
        mailDo.setReplyTo(relyTo.toString());
        mailDo.setIsContainsFile(isContainAttach(a));

        mailDo.setMsgId(msgId);
        mailDo.setReceivedDate(a.getReceivedDate());
        mailDo.setSendDate(a.getSentDate());
        mailDo.setSubject(EmojiConverterUtil.emojiConvert1(a.getSubject() == null ? "" : a.getSubject()));
        mailDo.setShopMailAccountId(accountId);
        //发件人
        InternetAddress address = (InternetAddress) mimeMessage.getSender();
        String sender = "";
        String senderNick = "";
        Enumeration<Header> list = mimeMessage.getAllHeaders();
        while (list.hasMoreElements()) {
            Header header = list.nextElement();
            String name = header.getName();
            String value = header.getValue();
            if ("From".equals(name)) {
                sender = MimeUtility.decodeText(value.replace("\"", ""));
                if (sender.lastIndexOf(">") != -1) {
                    sender = sender.substring(0, sender.lastIndexOf(">"));
                    String[] senderAnd = sender.split("<");
                    sender = senderAnd[1];
                    senderNick = senderAnd[0];
                }
            } else if ("To".equals(name)) {
                String to = MimeUtility.decodeText(value.replace("\"", ""));
                mailDo.setMailTo(to.replaceAll(",", ";"));
            }
        }
        if (StringUtils.isBlank(sender)) {
            sender = MimeUtility.decodeText(address == null || address.getAddress() == null ? "" : address.getAddress());
            senderNick = MimeUtility.decodeText(address == null || address.getPersonal() == null ? "" : address.getPersonal());
        }
        mailDo.setSender(EmojiConverterUtil.emojiConvert1(sender));
        mailDo.setSenderNick(org.apache.commons.lang3.StringUtils.isBlank(senderNick) ? "" : EmojiConverterUtil.emojiConvert1(senderNick));
        if ("".equals(StaticDict.Mail_Folder_Type.getText(type))) {
            if (mailDo.getMailTo().contains(mailNo) && !mailDo.getSender().equals(mailNo)) {
                type = StaticDict.Mail_Folder_Type.INBOX.getValue();
            } else if (mailDo.getSender().equals(mailNo)) {
                type = StaticDict.Mail_Folder_Type.OUTBOX.getValue();
            } else {
                type = StaticDict.Mail_Folder_Type.INBOX.getValue();
            }
        }
        mailDo.setType(type);
        mailDo.setFolderName(folderName);
        if (et == null) {
            dao.insert(mailDo);
            if (mailDo.getIsContainsFile()) {
                List<Map> fileIdList = new ArrayList<>();
                saveAttachMent(a, mailDo.getId(), fileIdList);
                String htmlStr = html.toString();
                for (Map map : fileIdList) {
                    Object fId = map.get("fileId");
                    Object cid = map.get("Content-ID");
                    if (fId == null || cid == null) {
                        continue;
                    }
                    Long fileId = Long.parseLong(fId.toString());
                    String contentId = cid.toString();
                    FileDo fileDo = fileService.getById(fileId);
                    if (fileDo == null) {
                        continue;
                    }
//                    String str = "<img src=\"cid:" + fileDo.getFileName().substring(0, fileDo.getFileName().lastIndexOf("."));
                    String str = "src=\"cid:" + contentId;
                    if (htmlStr.contains(str)) {
                        String newStr = "src=\"" + fileService.getFilePath(fileId);
                        htmlStr = StringUtils.replace(htmlStr, str, newStr);
                    }
                }
                mailDo.setTextHtml(EmojiConverterUtil.emojiConvert1(htmlStr));
                dao.updateById(mailDo);
            }

            //FBA约仓新邮件 需要匹配 亚马逊确认时间
            if ("FBA约仓".equals(mailDo.getFolderName()) && StringUtils.isNotBlank(mailDo.getSubject())) {
                String appointmentCode = tailTrucksService.getAppointmentCodeByMail(mailDo.getSubject());
                Date amazonTime = tailTrucksService.getAmazonTimeByMail(mailDo.getSubject());

                if (StringUtils.isNotBlank(appointmentCode)) {
                    this.updateAmazon(appointmentCode, amazonTime);
                    //插入到 新表
                    TailTrucksAmazonTimeDo timeDo = new TailTrucksAmazonTimeDo();
                    timeDo.setMailId(mailDo.getId());
                    timeDo.setAppointmentCode(appointmentCode);
                    timeDo.setAmazonTime(amazonTime);
                    tailTrucksAmazonTimeDao.insert(timeDo);
                }
            } else if ("SKL".equals(mailDo.getFolderName())) {
                String str1 = "筋斗雲(株)";
                String str2 = "btoc出荷情報のお知らせ";
                if (mailDo.getSubject().contains(str1) && mailDo.getSubject().contains(str2)) {
                    FileMoreDo fileMoreDo = fileMoreDao.selectOne(new LambdaQueryWrapper<FileMoreDo>()
                            .eq(FileMoreDo::getMailId, mailDo.getId())
                            .eq(FileMoreDo::getType, "mail"));
                    if (fileMoreDo == null) {
                        return;
                    }
                    FileDo fileDo = fileService.getById(fileMoreDo.getFileId());
                    File file = fileService.getFile(fileService.getFilePath(fileMoreDo.getFileId()), filePathTemp + File.separator + fileDo.getId() + "." + fileDo.getFileSuffix());
                    FileInputStream in = new FileInputStream(file);
                    InputStreamReader inReader = new InputStreamReader(in, StandardCharsets.UTF_8);
                    BufferedReader bufReader = new BufferedReader(inReader);
                    StringBuilder result = new StringBuilder();
                    String line = null;
                    while ((line = bufReader.readLine()) != null) {
                        if (result.length() > 0) {
                            result.append("\r\n");
                        }
                        result.append(line);
                    }
                    bufReader.close();

                    inReader.close();
                    in.close();
//                    List<OrderOutPutImportVo> orderOutPutImportVos = ExcelUtils.importExcel(new FileInputStream(file), 0, 1, false, OrderOutPutImportVo.class);
                    List<OrderOutputTrackNumberExcelImport> excelImportList = new ArrayList<>();
                    for (int i1 = 1; i1 < result.toString().split("\r\n").length; i1++) {
                        String value = result.toString().split("\r\n")[i1];
                        OrderOutputTrackNumberExcelImport vo = new OrderOutputTrackNumberExcelImport();
                        vo.setOrderOTNumber(value.split("\",\"")[8]);
                        String s = value.split("\",\"")[12];
                        if (StringUtils.isNotBlank(s)) {
                            vo.setTrackNumber(s.substring(0, s.length() - 1));
                        } else {
                            //防止错行
                            s = value.split("\",\"")[value.split("\",\"").length];
                            if (StringUtils.isNotBlank(s) && s.length() == 12) {
                                vo.setTrackNumber(s.substring(0, s.length() - 1));
                            }
                        }
                        excelImportList.add(vo);
                    }

                    orderOutputService.dealwithExcelData(excelImportList, 5, 1L);

                }
            }

        } else {
            mailDo.setCustomId(et.getCustomId());
            mailDo.setId(et.getId());
            BeanUtils.copyProperties(mailDo, et);
            dao.updateById(et);
        }
//        if (!isRead) {
//            mimeMessage.setFlag(Flags.Flag.SEEN, false);
//        }
    }

    public void updateAmazon(String appointmentCode, Date amazonTime) {

        List<TailTrucksDo> tailTrucksDoList = tailTrucksDao.selectList(new LambdaQueryWrapper<TailTrucksDo>()
                .ne(TailTrucksDo::getStatus, 4).and(i -> {
                    i.eq(TailTrucksDo::getAppointmentCode, appointmentCode).or()
                            .eq(TailTrucksDo::getAppointmentCode2, appointmentCode).or()
                            .eq(TailTrucksDo::getAppointmentCode3, appointmentCode);
                }));
        for (TailTrucksDo tailTrucksDo : tailTrucksDoList) {
            LambdaUpdateWrapper<TailTrucksDo> updateWrapper = new LambdaUpdateWrapper<>();
            if (StringUtils.isNotBlank(tailTrucksDo.getAppointmentCode()) && appointmentCode.equals(tailTrucksDo.getAppointmentCode())) {
                //将 亚马逊确认时间 更新成null
                updateWrapper.set(TailTrucksDo::getAmazonTime, amazonTime);
                if (tailTrucksDo.getAmazonTime() == null && amazonTime != null) {
                    updateWrapper.set(TailTrucksDo::getTimeStatus, "normal");
                } else {
                    updateWrapper.set(TailTrucksDo::getTimeStatus, "unnormal");
                }

            } else if (StringUtils.isNotBlank(tailTrucksDo.getAppointmentCode2()) && appointmentCode.equals(tailTrucksDo.getAppointmentCode2())) {
                updateWrapper.set(TailTrucksDo::getAmazonTime2, amazonTime);
                if (tailTrucksDo.getAmazonTime2() == null && amazonTime != null) {
                    updateWrapper.set(TailTrucksDo::getTimeStatus2, "normal");
                } else {
                    updateWrapper.set(TailTrucksDo::getTimeStatus2, "unnormal");
                }
            } else if (StringUtils.isNotBlank(tailTrucksDo.getAppointmentCode3()) && appointmentCode.equals(tailTrucksDo.getAppointmentCode3())) {
                updateWrapper.set(TailTrucksDo::getAmazonTime3, amazonTime);
                if (tailTrucksDo.getAmazonTime3() == null && amazonTime != null) {
                    updateWrapper.set(TailTrucksDo::getTimeStatus3, "normal");
                } else {
                    updateWrapper.set(TailTrucksDo::getTimeStatus3, "unnormal");
                }
            }
            updateWrapper.eq(TailTrucksDo::getId, tailTrucksDo.getId());

            tailTrucksService.update(updateWrapper);
        }

    }

    /**
     * 验证邮箱连接
     *
     * @param smtpHost
     * @param imapHost
     * @param mailNo
     * @param password
     * @return
     * @throws Exception
     */
    public Store getIMAPStore(String smtpHost, String imapHost, String mailNo, String password) throws Exception {
        if (StaticDict.Mail_Type.Outlook.getSmtp().equals(smtpHost)) {
//        String host = "outlook.office365.com";// change accordingly
            String mailStoreType = "imap";
            String popPort = "993";
            // 配置连接信息
            Properties properties = new Properties();
            properties.setProperty("mail.imap.partialfetch", "false");
            properties.setProperty("mail.imaps.partialfetch", "false");
            properties.put("mail.store.protocol", mailStoreType);
            properties.put("mail.imap.host", imapHost);
            properties.put("mail.imap.port", popPort);
            properties.put("mail.imap.starttls.enable", "true");
            Session emailSession = Session.getDefaultInstance(properties);
//            emailSession.setDebug(true);
            Store store = emailSession.getStore("imaps");
            store.connect(imapHost, mailNo, password);
            return store;
        } else if (StaticDict.Mail_Type.Gmail.getSmtp().equals(smtpHost)) {
            //https://www.google.com/settings/security/lesssecureapps   启用不够安全的应用的访问权限
            Properties props = System.getProperties();
            props.setProperty("mail.imap.partialfetch", "false");
            props.setProperty("mail.imaps.partialfetch", "false");
            props.setProperty("mail.store.protocol", "imaps");//设置电子邮件协议
            Session session = Session.getDefaultInstance(props, null);
            Store store = session.getStore("imaps");
            store.connect("imap.googlemail.com", mailNo, password);
            return store;
        } else {
            return this.getUStore(smtpHost, imapHost, mailNo, password);
        }
    }

    /**
     * 此方法适配连接网易云以及qq
     *
     * @param smtpHost
     * @param imapHost
     * @param mailNo
     * @param password
     * @return
     * @throws Exception
     */
    public IMAPStore getUStore(String smtpHost, String imapHost, String mailNo, String password) throws Exception {
        Properties props = System.getProperties();
        props.setProperty("mail.store.protocol", "imap");
        props.setProperty("mail.imap.host", imapHost);
        props.setProperty("mail.imap.port", "143");
        props.setProperty("mail.imap.partialfetch", "false");
        props.setProperty("mail.imaps.partialfetch", "false");
        HashMap<String, String> IAM = new HashMap<>();
        //带上IMAP ID信息，由key和value组成，例如name，version，vendor，support-email等。
        //解决 163邮箱不安全登录问题
        IAM.put("name", "myname");
        IAM.put("version", "1.0.0");
        IAM.put("vendor", "myclient");
        IAM.put("support-email", mailNo);
        Session session1 = Session.getInstance(props);
        IMAPStore store = (IMAPStore) session1.getStore("imap");
        store.connect(mailNo, password);//账号 //授权码
        store.id(IAM);
        return store;
    }


    /**
     * 判断此邮件是否包含附件
     */
    public boolean isContainAttach(Part part) throws Exception {
        boolean attachFlag = false;
        if (part.isMimeType("multipart/*")) {
            Multipart mp = (Multipart) part.getContent();
            for (int i = 0; i < mp.getCount(); i++) {
                BodyPart mPart = mp.getBodyPart(i);
                String disposition = mPart.getDisposition();
                if ((disposition != null) && ((disposition.equals(Part.ATTACHMENT)) || (disposition.equals(Part.INLINE))))
                    attachFlag = true;
                else if (mPart.isMimeType("multipart/*")) {
                    attachFlag = isContainAttach(mPart);
                } else {
                    String contype = mPart.getContentType();
                    if (contype.toLowerCase().contains("application"))
                        attachFlag = true;
                    if (contype.toLowerCase().contains("name"))
                        attachFlag = true;
                }
            }
        } else if (part.isMimeType("message/rfc822")) {
            attachFlag = isContainAttach((Part) part.getContent());
        }
        return attachFlag;
    }

    /**
     * 获取收件人，抄送人，密送人
     *
     * @param type
     * @return
     * @throws Exception
     */
    public String syncMailAddress(Message.RecipientType type, Message mimeMessage) throws Exception {
        String to = "";
        InternetAddress[] address = null;
        address = (InternetAddress[]) mimeMessage.getRecipients(type);
        if (address != null) {
            for (int i = 0; i < address.length; i++) {
                String email = address[i].getAddress();
                if (email == null)
                    email = "";
                else {
                    email = MimeUtility.decodeText(email.trim());
                }
                String personal = address[i].getPersonal();
                if (personal == null)
                    personal = email.split("@")[0];
                else {
                    personal = MimeUtility.decodeText(personal.replaceAll("\"", "").trim());
                }
                String compositeto = personal + "<" + email + ">";
                to += ";" + compositeto;
            }
            to = to.substring(1);
        }
        return to;
    }


    /**
     * 获取正文
     *
     * @param part
     * @param plain
     * @throws Exception
     */
    public void getMailContent(Part part, StringBuilder plain, StringBuilder html) throws Exception {
        String contentType = part.getContentType();
        int nameIndex = contentType.indexOf("name");
        boolean conName = false;
        if (nameIndex != -1)
            conName = true;
//        System.out.println("CONTENTTYPE: " + contentType);
        if (part.isMimeType("text/plain") && !conName) {
            plain.append((String) part.getContent());
        } else if (part.isMimeType("text/html") && !conName) {
            html.append((String) part.getContent());
        } else if (part.isMimeType("multipart/*")) {
            Multipart multipart = (Multipart) part.getContent();
            int counts = multipart.getCount();
            for (int i = 0; i < counts; i++) {
                getMailContent(multipart.getBodyPart(i), plain, html);
            }
        } else if (part.isMimeType("message/rfc822")) {
            getMailContent((Part) part.getContent(), plain, html);
        } else {
        }
    }


    /**
     * 【判断此邮件是否已读，如果未读返回返回false,反之返回true】
     */
    public boolean isNew(Message mimeMessage) throws MessagingException {
        boolean isNew = false;
        Flags flags = (mimeMessage).getFlags();
        Flags.Flag[] flag = flags.getSystemFlags();
//        System.out.println("flags's length: " + flag.length);
        for (int i = 0; i < flag.length; i++) {
            if (flag[i] == Flags.Flag.SEEN) {
                isNew = true;
//                System.out.println("seen Message.......");
                break;
            }
        }

        return isNew;
    }

    /**
     * 【保存附件】
     */
    public void saveAttachMent(Part part, Long mailId, List<Map> fileIdList) throws Exception {
        String fileName = "";
        if (part.isMimeType("multipart/*")) {
            Multipart mp = (Multipart) part.getContent();
            for (int i = 0; i < mp.getCount(); i++) {
                BodyPart mpart = mp.getBodyPart(i);
                String disposition = mpart.getDisposition();
                if ((disposition != null) && ((disposition.equals(Part.ATTACHMENT)) || (disposition.equals(Part.INLINE)))) {
                    fileName = mpart.getFileName();
                    // if (StringUtils.isNotBlank(fileName) && (fileName.toLowerCase().contains("gb") || fileName.toLowerCase().contains("utf-8"))) {
                    if (org.apache.commons.lang3.StringUtils.isNotBlank(fileName)) {
                        fileName = MimeUtility.decodeText(fileName);
                    }
                    getFileId(fileName, mailId, fileIdList, mpart);
                } else if (mpart.isMimeType("multipart/*")) {
                    saveAttachMent(mpart, mailId, fileIdList);
                } else {
                    fileName = mpart.getFileName();
                    if ((fileName != null)) {
                        System.out.println("附件名称(未解码)：" + fileName);
                        fileName = MimeUtility.decodeText(fileName);
                    }
                    getFileId(fileName, mailId, fileIdList, mpart);

                }
            }
        } else if (part.isMimeType("message/rfc822")) {
            saveAttachMent((Part) part.getContent(), mailId, fileIdList);
        }
    }


    public void getFileId(String fileName, Long mailId, List<Map> fileIdList, BodyPart mpart) {
        if (org.apache.commons.lang3.StringUtils.isBlank(fileName)) {
            return;
        }
        Map map = new HashMap();
        try {
            Enumeration<Header> list = mpart.getAllHeaders();
            while (list.hasMoreElements()) {
                Header header = list.nextElement();
                String name = header.getName();
                String value = header.getValue();
                if ("Content-ID".equalsIgnoreCase(name)) {
                    map.put("Content-ID", value.substring(1, value.length() - 1));
                }
//            else if ("Content-Disposition".equals(name)){
//                map.put("type",value.startsWith("inline") ? "inline" : "attachment");
//            }
            }
        } catch (MessagingException e) {
            e.printStackTrace();
        }

        try {

            //方案一：先上传到临时文件夹，再上传到正式文件夹
//            Long fileId = fileService.uploadTempFile(fileName, mpart.getInputStream(), null);
//            addFileMoreDo(fileId, mailId);
//            fileService.uploadFile(fileId);
            //方案二 直接上传到正式路径
            Long fileId = fileService.uploadFileToFormalPath(mpart.getInputStream(), fileName);
            if (fileId == 0L) {
                return;
            }
            addFileMoreDo(fileId, mailId);

            map.put("fileId", fileId);
            fileIdList.add(map);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    public void addFileMoreDo(Long fileId, Long mailId) {
        if (fileId != null && fileId != 0L) {
            FileMoreDo fileMoreDo = new FileMoreDo();
            fileMoreDo.setFileId(fileId);
            fileMoreDo.setMailId(mailId);
            fileMoreDo.setType(StaticDict.File_Type.Mail.getValue());
            fileMoreDo.setCreateTime(new Date());
            fileMoreDao.insert(fileMoreDo);
        }
    }


}
